#include <qfile.h>
#include <qdatetime.h>
#include <qmessagebox.h>
#include <qdebug.h>
#include <openssl/evp.h>

#include "license_manager.h"

bool LicenseManager::verifyLicense()
{
    QByteArray readKey;
    QByteArray readEncryptedData;

    if (!readLicense(readEncryptedData, readKey)) {
        showError(tr("Failed to read license files!"));
        return false;
    }

    QByteArray decryptedData;
    if (!decryptAes(readEncryptedData, readKey, decryptedData)) {
        showError(tr("Failed to decrypt license data!"));
        return false;
    }

    QList<QByteArray> decryptedParts = decryptedData.split('|');
    if (decryptedParts.size() != 2) {
        showError(tr("Failed to parse the License.lic file!"));
        return false;
    }

    QString startDateStr = decryptedParts[0];
    QString endDateStr = decryptedParts[1].left(10);
    if (!isCurrentDateInRange(startDateStr, endDateStr)) {
        showError(tr("The current date is not valid!"));
        return false;
    }

    return true;
}

bool LicenseManager::decryptAes(const QByteArray& encryptedData, const QByteArray& key, QByteArray& decrypted)
{
    if (key.size() != 16) {
        qDebug() << "Invalid key size. AES-128 requires a 16-byte key.";
        return false;
    }

    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    if (!ctx) {
        qDebug() << "Failed to create EVP context.";
        return false;
    }
    if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ecb(), nullptr, reinterpret_cast<const unsigned char*>(key.data()), nullptr)) {
        qDebug() << "Failed to initialize decryption.";
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }
    EVP_CIPHER_CTX_set_padding(ctx, 0);
    decrypted.resize(encryptedData.size());

    int decryptedLength = 0;
    if (1 != EVP_DecryptUpdate(ctx, reinterpret_cast<unsigned char*>(decrypted.data()), &decryptedLength,
        reinterpret_cast<const unsigned char*>(encryptedData.data()), encryptedData.size())) {
        qDebug() << "Failed to decrypt data.";
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }

    int finalLength = 0;
    if (1 != EVP_DecryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(decrypted.data()) + decryptedLength, &finalLength)) {
        qDebug() << "Failed to finalize decryption.";
        EVP_CIPHER_CTX_free(ctx);
        return false;
    }
    decryptedLength += finalLength;
    decrypted.resize(decryptedLength);

    EVP_CIPHER_CTX_free(ctx);
    return true;
}

bool LicenseManager::readLicense(QByteArray& encryptedData, QByteArray& key)
{
    QFile keyFile("License.key");
    if (!keyFile.open(QIODevice::ReadOnly)) {
        qDebug() << "Unable to open License.key for reading.";
        return false;
    }
    key = keyFile.readAll();
    keyFile.close();

    QFile licFile("License.lic");
    if (!licFile.open(QIODevice::ReadOnly)) {
        qDebug() << "Unable to open License.lic for reading.";
        return false;
    }
    encryptedData = licFile.readAll();
    licFile.close();

    return true;
}

bool LicenseManager::isCurrentDateInRange(const QString& startDateStr, const QString& endDateStr)
{
    QDate startDate = QDate::fromString(startDateStr, "yyyy-MM-dd");
    QDate endDate = QDate::fromString(endDateStr, "yyyy-MM-dd");

    if (!startDate.isValid() || !endDate.isValid()) {
        qDebug() << "Invalid date format!";
        return false;
    }

    QDate currentDate = QDate::currentDate();
    qDebug() << "Current date:" << currentDate.toString("yyyy-MM-dd");

    return (currentDate >= startDate && currentDate <= endDate);
}

void LicenseManager::showError(const QString& message)
{
    QPixmap icon(":/icon/EFlow.ico");
    QMessageBox msgBox;
    msgBox.setWindowIcon(icon);
    msgBox.setIcon(QMessageBox::Critical);
    msgBox.setWindowTitle(tr("Error"));
    msgBox.setText(message);
    msgBox.exec();
}